package aliyun.cx.admin.config;

import aliyun.cx.admin.security.JwtAuthenticationEntryPoint;
import aliyun.cx.admin.security.JwtAuthenticationFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfigurationSource;

/**
 * Spring Security 配置
 */
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
@RequiredArgsConstructor
public class SecurityConfig {

    private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
    private final JwtAuthenticationFilter jwtAuthenticationFilter;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http, CorsConfigurationSource corsConfigurationSource) throws Exception {
        http
            // 禁用CSRF保护（JWT不需要CSRF保护）
            .csrf(csrf -> csrf.disable())
            
            // 配置CORS
            .cors(cors -> cors.configurationSource(corsConfigurationSource))
            
            // 设置会话创建策略为无状态
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            
            // 配置异常处理
            .exceptionHandling(ex -> ex
                .authenticationEntryPoint(jwtAuthenticationEntryPoint)
            )
            
            // 配置授权规则
            .authorizeHttpRequests(authz -> authz
                // 允许登录和登出接口
                .requestMatchers("/api/admin/login", "/api/admin/logout").permitAll()
                // 允许文件访问
                .requestMatchers("/api/upload/images/**").permitAll()
                // 允许健康检查
                .requestMatchers("/actuator/**", "/health", "/info").permitAll()
                // 允许OPTIONS请求（预检请求）
                .requestMatchers("OPTIONS", "/**").permitAll()
                // 用户管理接口需要认证
                .requestMatchers("/api/admin/users/**", "/api/admin/user/info", "/api/admin/profile/**").authenticated()
                // 角色管理接口需要认证
                .requestMatchers("/api/admin/roles/**").authenticated()
                // 权限管理接口需要认证
                .requestMatchers("/api/admin/permissions/**").authenticated()
                // 文章管理接口需要认证
                .requestMatchers("/api/admin/articles/**").authenticated()
                // 评论管理接口需要认证
                .requestMatchers("/api/comments/**").authenticated()
                // 分类标签管理接口需要认证
                .requestMatchers("/api/admin/categories/**", "/api/admin/tags/**").authenticated()
                // 相册管理接口需要认证
                .requestMatchers("/api/album/**").authenticated()
                // 系统配置接口需要认证
                .requestMatchers("/api/config/**").authenticated()
                // 文件上传接口需要认证
                .requestMatchers("/api/upload/**").authenticated()
                // 系统监控接口需要认证
                .requestMatchers("/api/system/**").authenticated()
                // 仪表盘接口需要认证
                .requestMatchers("/api/dashboard/**").authenticated()
                // 其他所有请求需要认证
                .anyRequest().authenticated()
            )
            
            // 禁用表单登录
            .formLogin(form -> form.disable())
            
            // 禁用HTTP Basic认证
            .httpBasic(basic -> basic.disable())
            
            // 添加JWT认证过滤器
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
        
        return http.build();
    }
}
